package com.github.ilioili.justdoit.util;

import android.content.res.Resources;

import com.github.ilioili.justdoit.R;
import com.github.ilioili.justdoit.model.pojo.ScheduleEvent;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * Created by hantuo on 16/5/26.
 */
public class DateUtil {
    public static final long DAY_MILISECOND = 24 * 60 * 60 * 1000;


    public static boolean isToday(long time) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.setTimeInMillis(time);
        return year == calendar.get(Calendar.YEAR) && month == calendar.get(Calendar.MONTH) && day == calendar.get(Calendar.DAY_OF_MONTH);
    }

    public static boolean isTomorrow(long time) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.setTimeInMillis(time - DAY_MILISECOND);
        return year == calendar.get(Calendar.YEAR) && month == calendar.get(Calendar.MONTH) && day == calendar.get(Calendar.DAY_OF_MONTH);
    }

    public static boolean isTheDayAfterTomorrow(long time) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.setTimeInMillis(time - 2 * DAY_MILISECOND);
        return year == calendar.get(Calendar.YEAR) && month == calendar.get(Calendar.MONTH) && day == calendar.get(Calendar.DAY_OF_MONTH);
    }

    public static boolean isYestoday(long time) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.setTimeInMillis(time + DAY_MILISECOND);
        return year == calendar.get(Calendar.YEAR) && month == calendar.get(Calendar.MONTH) && day == calendar.get(Calendar.DAY_OF_MONTH);
    }


    public static boolean isThisWeek(long time) {
        return time >= getWeekStartTime() && time < getWeekEndTime();
    }

    public static boolean isNextWeek(long time) {
        time -= DAY_MILISECOND * 7;
        return isThisWeek(time);
    }

    public static boolean isThisMonth(long time) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        calendar.setTimeInMillis(time);
        return year == calendar.get(Calendar.YEAR) && month == calendar.get(Calendar.MONTH);
    }

    public static int dayOffsetFromNow(long time) {
        Calendar calendar = Calendar.getInstance();
        clearHms(calendar);
        long todayStartTime = calendar.getTimeInMillis();
        calendar.setTimeInMillis(time);
        clearHms(calendar);
        long theGivenDayStartTime = calendar.getTimeInMillis();
        return (int) ((todayStartTime - theGivenDayStartTime) / DAY_MILISECOND);
    }

    public static boolean isBeforeYestoday(long time) {
        Calendar calendar = Calendar.getInstance();
        clearHms(calendar);
        return time < calendar.getTimeInMillis() - DAY_MILISECOND;
    }

    public static boolean isBeforeToday(long time) {
        Calendar calendar = Calendar.getInstance();
        clearHms(calendar);
        return time < calendar.getTimeInMillis();
    }

    public static boolean isAfterToday(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(year, month, day);
        return getTodayStartTime() + DAY_MILISECOND <= calendar.getTimeInMillis();
    }

    public static long getAlarmTime(ScheduleEvent scheduleEvent) {
        Calendar calendar = Calendar.getInstance();
        if (scheduleEvent.startTime < getTodayStartTime()) {
            calendar.setTimeInMillis(System.currentTimeMillis());
        } else {
            calendar.setTimeInMillis(scheduleEvent.startTime);
        }
        clearHms(calendar);
        calendar.set(Calendar.HOUR_OF_DAY, scheduleEvent.alermHour);
        calendar.set(Calendar.MINUTE, scheduleEvent.alermMinute);
        return calendar.getTimeInMillis();
    }

    /**
     * @param "星期一"、"星期二"。。。
     * @return
     */
    public static String getWeekDay(Resources resource, long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        switch (dayOfWeek) {
            case Calendar.MONDAY:
                return resource.getString(R.string.monday);
            case Calendar.TUESDAY:
                return resource.getString(R.string.tuesday);
            case Calendar.WEDNESDAY:
                return resource.getString(R.string.wednesday);
            case Calendar.THURSDAY:
                return resource.getString(R.string.thusday);
            case Calendar.FRIDAY:
                return resource.getString(R.string.friday);
            case Calendar.SATURDAY:
                return resource.getString(R.string.saterday);
            default:
                return resource.getString(R.string.sunday);
        }
    }

    private static SimpleDateFormat sdfMonthDay = new SimpleDateFormat("MM月dd号");

    public static String getMonthDay(long time) {
        return sdfMonthDay.format(time);
    }

    /**
     * clear Hour Minute Second Millisecond
     */
    public static long clearHmsm(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        clearHms(calendar);
        return calendar.getTimeInMillis();
    }

    public static long getTodayStartTime() {
        Calendar calendar = Calendar.getInstance();
        clearHms(calendar);
        return calendar.getTimeInMillis();
    }

    public static long getTodayEndTime() {
        Calendar calendar = Calendar.getInstance();
        clearHms(calendar);
        return calendar.getTimeInMillis() + DAY_MILISECOND;
    }

    public static long getWeekEndTime() {
        Calendar calendar = Calendar.getInstance();
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        dayOfWeek--;
        if (dayOfWeek == 0) dayOfWeek = 7;
        int offset = 8 - dayOfWeek;
        return getTodayStartTime() + offset * DAY_MILISECOND;
    }

    public static long getWeekStartTime() {
        Calendar calendar = Calendar.getInstance();
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        dayOfWeek -= 2;
        if (dayOfWeek == -1) dayOfWeek = 6;
        return getTodayStartTime() - dayOfWeek * DAY_MILISECOND;
    }

    public static long getDayStartTime(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        clearHms(calendar);
        return calendar.getTimeInMillis();
    }

    public static long getDayStartTime(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        clearHms(calendar);
        return calendar.getTimeInMillis();
    }

    public static boolean isTheLastDayOfMonth(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        return dayOfMonth == calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public static boolean isTheLastDayOfWeek(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek == Calendar.SUNDAY;
    }

    public static String getAlarmTimeStr(ScheduleEvent scheduleEvent) {
        long time = getAlarmTime(scheduleEvent);
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        String tiemFragment;
        if (hour < 5) {
            tiemFragment = " 凌晨 ";
        } else if (hour < 8) {
            tiemFragment = " 早上 ";
        } else if (hour < 12) {
            tiemFragment = " 上午 ";
        } else if (hour < 18) {
            tiemFragment = " 下午 ";
        } else if (hour < 23) {
            tiemFragment = " 晚上 ";
        } else {
            tiemFragment = " 深夜 ";
        }
        String dayStr;
        if (isToday(time)) {
            dayStr = "今天";
        } else if (isTomorrow(time)) {
            dayStr = "明天";
        } else if (isTheDayAfterTomorrow(time)) {
            dayStr = "后天";
        } else {
            dayStr = getYearMontDay(time);
        }
        String hourMinute = new SimpleDateFormat("hh:mm").format(time);
        return dayStr + tiemFragment + hourMinute;
    }


    public static String getYearMontDay(long time) {
        return new SimpleDateFormat("yyyy-MM-dd").format(time);
    }

    /**
     * @param startTime 如果7天后还是这个月，则返回7天后的时间，否则返回月底最后一天的时间
     * @return
     */
    public static long getTimeLaterInThisMonth(long startTime) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(startTime);
        int month = calendar.get(Calendar.MONTH);
        calendar.setTimeInMillis(startTime + 7 * DAY_MILISECOND);
        int afterMonth = calendar.get(Calendar.MONTH);
        if (month == afterMonth) {
            return calendar.getTimeInMillis();
        } else {
            calendar.setTimeInMillis(startTime);
            calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
            clearHms(calendar);
            return calendar.getTimeInMillis();
        }
    }

    public static long getTimeLaterInThisWeek(long startTime) {
        Calendar calendar = Calendar.getInstance();
        Locale.setDefault(Locale.CHINA);
        calendar.setTimeInMillis(startTime);
        int week = calendar.get(Calendar.WEEK_OF_YEAR);
        calendar.setTimeInMillis(startTime + 3 * DAY_MILISECOND);
        int afterWeek = calendar.get(Calendar.WEEK_OF_YEAR);
        if (week == afterWeek) {
            return calendar.getTimeInMillis();
        } else {
            calendar.setTimeInMillis(startTime);
            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
            if (dayOfWeek == Calendar.SUNDAY) {
                return startTime;
            } else {
                calendar.setTimeInMillis(startTime + (7 - dayOfWeek) * DAY_MILISECOND);
                clearHms(calendar);
                return calendar.getTimeInMillis();
            }
        }
    }

    public static int getTotalMatchedDayNum(ScheduleEvent scheduleEvent, long endTime) {
        Date date = new Date();
        int matchNum = 0;
        for (long time = DateUtil.getDayStartTime(scheduleEvent.startTime); time < endTime; time += DAY_MILISECOND) {
            date.setTime(time);
            if (DateRepeatUtil.matchTheDay(scheduleEvent.repeatFlag, date)) {
                matchNum++;
            }
        }
        return matchNum;
    }

    private static void clearHms(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
    }


    public static boolean isAfterNextWeek(long startTime) {
        long endTime = getWeekEndTime() + DAY_MILISECOND * 7;
        return startTime >= endTime;
    }
}
